/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package cn.zzdt4j.core.executor;

import cn.zzdt4j.core.executor.plugin.manager.DefaultThreadPoolPluginManager;
import cn.zzdt4j.core.executor.plugin.manager.DefaultThreadPoolPluginRegistrar;
import lombok.Getter;
import lombok.NonNull;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;

/**
 * Dynamic thread-pool
 *
 * @author by <a href="mailto:ligang941012@gmail.com">gang.Li</a>
 * @since 2023/9/14 1:41
 */
@Slf4j
public class DynamicThreadPoolExecutor extends ExtensibleThreadPoolExecutor {

    @Setter
    @Getter
    private long executeTimeOut;

    @Setter
    @Getter
    private boolean waitForTasksToCompleteOnShutdown;

    @Setter
    @Getter
    private long awaitTerminationMillis;

    /**
     * Creates a new {@code DynamicThreadPoolExecutor} with the given initial parameters.
     *
     * @param threadPoolId                     thread-pool id
     * @param executeTimeOut                   execute time out
     * @param waitForTasksToCompleteOnShutdown wait for tasks to complete on shutdown
     * @param awaitTerminationMillis           await termination millis
     * @param corePoolSize                     the number of threads to keep in the pool, even
     *                                         if they are idle, unless {@code allowCoreThreadTimeOut} is set
     * @param maximumPoolSize                  the maximum number of threads to allow in the
     *                                         pool
     * @param keepAliveTime                    when the number of threads is greater than
     *                                         the core, this is the maximum time that excess idle threads
     *                                         will wait for new tasks before terminating.
     * @param timeUnit                         the time unit for the {@code keepAliveTime} argument
     * @param blockingQueue                    the queue to use for holding tasks before they are
     *                                         executed.  This queue will hold only the {@code Runnable}
     *                                         tasks submitted by the {@code execute} method.
     * @param threadFactory                    the factory to use when the executor creates a new thread
     * @param rejectedExecutionHandler         the handler to use when execution is blocked because the thread bounds and queue capacities are reached
     * @throws IllegalArgumentException if one of the following holds:<br>
     *                                  {@code corePoolSize < 0}<br>
     *                                  {@code keepAliveTime < 0}<br>
     *                                  {@code maximumPoolSize <= 0}<br>
     *                                  {@code maximumPoolSize < corePoolSize}
     * @throws NullPointerException     if {@code workQueue}
     *                                  or {@code threadFactory} or {@code handler} is null
     */
    public DynamicThreadPoolExecutor(@NonNull String threadPoolId, int corePoolSize,
                                     int maximumPoolSize,
                                     long keepAliveTime,
                                     TimeUnit timeUnit,
                                     long executeTimeOut, boolean waitForTasksToCompleteOnShutdown,
                                     long awaitTerminationMillis,
                                     @NonNull BlockingQueue<Runnable> blockingQueue,
                                     @NonNull ThreadFactory threadFactory,
                                     @NonNull RejectedExecutionHandler rejectedExecutionHandler) {
        super(threadPoolId, new DefaultThreadPoolPluginManager().setPluginComparator(AnnotationAwareOrderComparator.INSTANCE),
                corePoolSize, maximumPoolSize, keepAliveTime, timeUnit, blockingQueue, threadFactory, rejectedExecutionHandler);
        log.info("Initializing ExecutorService '{}'", threadPoolId);
        this.waitForTasksToCompleteOnShutdown = waitForTasksToCompleteOnShutdown;
        // Init default plugins
        new DefaultThreadPoolPluginRegistrar(executeTimeOut, awaitTerminationMillis).doRegister(this);
    }

}
